package controllers

import (
	"cid-media-api/global"
	dataSyncDirectorMaterialAuditDataWorker "cid-media-api/workers/data/sync-director-material-audit-data"
	dataSyncEditorMaterialAuditDataWorker "cid-media-api/workers/data/sync-editor-material-audit-data"
	dataTiktokSyncEditorMaterialAuditDataWorker "cid-media-api/workers/data/tiktok-sync-editor-material-audit-data"
	dataUpdateHistoryEditorMaterialAuditDataWorker "cid-media-api/workers/data/update-history-editor-material-audit-data"
	oceanQCGetAdvertiserReportDayJlnWorker "cid-media-api/workers/ocean-qc/get-advertiser-report/jln"
	oceanQCGetMaterialReportDayJlnWorker "cid-media-api/workers/ocean-qc/get-material-report-day/jln"
	oceanGetAdvertiserFundWorker "cid-media-api/workers/ocean/get-advertiser-fund"
	oceanGetAdvertiserFundDailyStatWorker "cid-media-api/workers/ocean/get-advertiser-fund-daily-stat"
	oceanGetAdvertiserReportDayWorker "cid-media-api/workers/ocean/get-advertiser-report/day"
	oceanGetAdvertiserReportDayJlnWorker "cid-media-api/workers/ocean/get-advertiser-report/jln"
	oceanGetMaterialReportDayJlnWorker "cid-media-api/workers/ocean/get-material-report-day/jln"
	"github.com/gin-gonic/gin"
	"github.com/go-redis/redis_rate/v10"
	"log"
	"net/http"
	"strconv"
	"sync"
	"sync/atomic"
	"time"
)

// TestRateLimit test rate limit given total requests num and rate(requests per second)
func TestRateLimit(ctx *gin.Context) {

	rate, _ := strconv.Atoi(ctx.DefaultQuery("rate", "10"))
	total, _ := strconv.Atoi(ctx.DefaultQuery("total", "50"))

	limit := redis_rate.Limit{
		Rate:   rate,
		Burst:  1,
		Period: time.Second,
	}
	wg := sync.WaitGroup{}
	wg.Add(total)

	var result sync.Map

	for i := 0; i < total; i++ {

		go func() {
			defer wg.Done()
			res, err := global.RateLimiter.Allow(ctx, "test-rl", limit)

			if res.RetryAfter <= 0 {
				log.Printf("allowed: %v, remaining: %v", res.Allowed, res.Remaining)
			}

			for res.RetryAfter > 0 {
				time.Sleep(res.RetryAfter)
				res, err = global.RateLimiter.Allow(ctx, "test-rl", limit)
				if res.RetryAfter <= 0 {
					log.Printf("allowed: %v, remaining: %v", res.Allowed, res.Remaining)
				}
			}

			curTime := time.Now().Format(time.DateTime)
			val, _ := result.LoadOrStore(curTime, new(int64))
			atomic.AddInt64(val.(*int64), 1)

			if err != nil {
				log.Fatalf("too many requests")
			}
		}()

	}

	wg.Wait()

	m := make(map[string]interface{})
	result.Range(func(key, value interface{}) bool {
		m[key.(string)] = value
		return true
	})

	ctx.JSON(http.StatusOK, m)
}

func TestGetAdvertiserFund(ctx *gin.Context) {
	advId, _ := strconv.Atoi(ctx.DefaultQuery("advertiser_id", "0"))
	oceanGetAdvertiserFundWorker.Execute(advId)

	ctx.JSON(http.StatusOK, gin.H{
		"data": "success",
	})
}

func TestGetAdvertiserFundDailyStat(ctx *gin.Context) {
	advId, _ := strconv.Atoi(ctx.DefaultQuery("advertiser_id", "0"))
	startDate := ctx.DefaultQuery("start_date", time.Now().Add(-24*time.Hour).Format(time.DateOnly))
	endDate := ctx.DefaultQuery("end_date", time.Now().Format(time.DateOnly))
	data := oceanGetAdvertiserFundDailyStatWorker.Execute(advId, startDate, endDate)

	ctx.JSON(http.StatusOK, gin.H{
		"data": data,
	})
}

func TestGetAdvertiserReportDay(ctx *gin.Context) {
	advId, _ := strconv.Atoi(ctx.DefaultQuery("advertiser_id", "0"))
	startDate := ctx.DefaultQuery("start_date", time.Now().Add(-24*time.Hour).Format(time.DateOnly))
	endDate := ctx.DefaultQuery("end_date", time.Now().Format(time.DateOnly))
	oceanGetAdvertiserReportDayWorker.Execute(advId, startDate, endDate)

	ctx.JSON(http.StatusOK, gin.H{
		"data": "success",
	})
}

func TestGetAdvertiserReportDayJln(ctx *gin.Context) {
	log.Printf("正在定时执行广告主报表数据拉取任务")
	advId, _ := strconv.Atoi(ctx.DefaultQuery("advertiser_id", "0"))
	startDate := ctx.DefaultQuery("start_date", time.Now().Add(-24*time.Hour).Format(time.DateOnly))
	endDate := ctx.DefaultQuery("end_date", time.Now().Format(time.DateOnly))
	oceanGetAdvertiserReportDayJlnWorker.Execute(advId, startDate, endDate, log.Default())

	ctx.JSON(http.StatusOK, gin.H{
		"data": "success",
	})
}

func TestGetMaterialReportDayJln(ctx *gin.Context) {
	advId, _ := strconv.Atoi(ctx.DefaultQuery("advertiser_id", "0"))
	startDate := ctx.DefaultQuery("start_date", time.Now().Format(time.DateOnly))
	endDate := ctx.DefaultQuery("end_date", time.Now().Format(time.DateOnly))
	oceanGetMaterialReportDayJlnWorker.Execute(advId, startDate, endDate, log.Default())

	ctx.JSON(http.StatusOK, gin.H{
		"data": "success",
	})
}

func TestSyncEditorMaterialAuditData(ctx *gin.Context) {
	startDate := ctx.DefaultQuery("start_date", time.Now().Format(time.DateOnly))
	endDate := ctx.DefaultQuery("end_date", time.Now().Format(time.DateOnly))
	dataSyncEditorMaterialAuditDataWorker.Execute(startDate, endDate, log.Default())

	ctx.JSON(http.StatusOK, gin.H{
		"data": "success",
	})
}

func TestUpdateHistoryEditorMaterialAuditData(ctx *gin.Context) {
	date := ctx.DefaultQuery("date", time.Now().Format(time.DateOnly))
	dataUpdateHistoryEditorMaterialAuditDataWorker.Execute(date, log.Default())

	ctx.JSON(http.StatusOK, gin.H{
		"data": "success",
	})
}

func TestSyncDirectorMaterialAuditData(ctx *gin.Context) {
	startDate := ctx.DefaultQuery("start_date", time.Now().Format(time.DateOnly))
	endDate := ctx.DefaultQuery("end_date", time.Now().Format(time.DateOnly))
	dataSyncDirectorMaterialAuditDataWorker.Execute(startDate, endDate, log.Default())

	ctx.JSON(http.StatusOK, gin.H{
		"data": "success",
	})
}

func TestGetQCAdvertiserReportDayJln(ctx *gin.Context) {
	log.Printf("正在定时执行千川广告主报表数据拉取任务")
	advId, _ := strconv.Atoi(ctx.DefaultQuery("advertiser_id", "0"))
	startDate := ctx.DefaultQuery("start_date", time.Now().Add(-24*time.Hour).Format(time.DateOnly))
	endDate := ctx.DefaultQuery("end_date", time.Now().Format(time.DateOnly))
	oceanQCGetAdvertiserReportDayJlnWorker.Execute(advId, startDate, endDate, log.Default())

	ctx.JSON(http.StatusOK, gin.H{
		"data": "success",
	})
}

func TestGetQCMaterialReportDayJln(ctx *gin.Context) {
	advId, _ := strconv.Atoi(ctx.DefaultQuery("advertiser_id", "0"))
	startDate := ctx.DefaultQuery("start_date", time.Now().Format(time.DateOnly))
	endDate := ctx.DefaultQuery("end_date", time.Now().Format(time.DateOnly))
	oceanQCGetMaterialReportDayJlnWorker.Execute(advId, startDate, endDate, log.Default())

	ctx.JSON(http.StatusOK, gin.H{
		"data": "success",
	})
}

func TestTiktokSyncEditorMaterialAuditData(ctx *gin.Context) {
	startDate := ctx.DefaultQuery("start_date", time.Now().Format(time.DateOnly))
	endDate := ctx.DefaultQuery("end_date", time.Now().Format(time.DateOnly))
	dataTiktokSyncEditorMaterialAuditDataWorker.Execute(startDate, endDate, log.Default())

	ctx.JSON(http.StatusOK, gin.H{
		"data": "success",
	})
}
